Skip to content

feat(reader): lazy DecimalByteParts decode#50

Merged
dfa1 merged 1 commit into
mainfrom
feat/decbyteparts-lazy
Jun 16, 2026
Merged

feat(reader): lazy DecimalByteParts decode#50
dfa1 merged 1 commit into
mainfrom
feat/decbyteparts-lazy

Conversation

@dfa1

@dfa1 dfa1 commented Jun 16, 2026

Copy link
Copy Markdown
Owner

Summary

Convert vortex.decimal_byte_parts decoding from a GenericArray wrap (with the child-array reassembly hard-coded into GenericArray.getDecimal) into a dedicated lazy LazyDecimalBytePartsArray record that owns its own reassembly.

Background

The pre-existing decoder wrapped the mantissa child in GenericArray(dtype, len, [], [mspChild]). The decimal-from-child path then lived inside GenericArray.getDecimal — buffers-vs-child shape dispatch, ptype switch on the child, BigInteger construction — fighting GenericArray's other role as the single-buffer fallback for vortex.decimal.

Changes

  • LazyDecimalBytePartsArray (record, implements Array) holds parent DType.Decimal, length, and the mantissa child. getDecimal(i) reads one cell from the child via a small package-private helper and combines it with the dtype scale to produce a BigDecimal on demand. No buffer materialisation at construction time.
  • DecimalBytePartsArrays (package-private) centralises the per-row mantissa read — dispatches Byte / Short / Int / Long Array, recurses through MaskedArray, throws on null cells.
  • DecimalBytePartsEncodingDecoder now returns LazyDecimalBytePartsArray directly.
  • GenericArray.getDecimal is reduced to the single-buffer layout only; the child-array branch and helper are gone.
  • ScanIterator truncate dispatch gains a LazyDecimalBytePartsArray case that recursively truncates the child and rebuilds the record at the clamped row count.
  • VortexInspectorTui data-cell renderer recognises both decimal flavours via a small tryDecimal helper taking the getter as a LongFunction.

Tests

  • Two GenericArrayTest cases that exercised the child-array shape moved to the new LazyDecimalBytePartsArrayTest, joined by a widening case (i32 child under decimal(15,2)) and the bounds / non-decimal-dtype guards.
  • The writer's DecimalBytePartsEncodingEncoderTest round-trip now asserts the reassembled BigDecimal value rather than reaching into GenericArray.child(0).

Test plan

  • ./mvnw verify — 13 modules SUCCESS, integration suite 40s green.
  • Branch rebased on top of latest main (no {@code} left in new Javadoc).

🤖 Generated with Claude Code

The pre-existing DecimalBytePartsEncodingDecoder wrapped the decoded
mantissa child in a GenericArray with zero buffers and one child. The
decimal-from-child reassembly logic then lived inside GenericArray —
buffers-vs-child shape dispatch, ptype switch on the child Array,
mantissa BigInteger construction — fighting GenericArray's other role
as the single-buffer fallback for vortex.decimal.

Introduce LazyDecimalBytePartsArray (record, implements Array) that owns
its own decimal reassembly. Its getDecimal(i) reads one cell from the
mantissa child via DecimalBytePartsArrays.readMantissa (a package-private
helper that dispatches Byte / Short / Int / Long Array, recurses through
MaskedArray, throws on null cells) and combines the result with the
parent DType.Decimal scale to produce a BigDecimal on demand. No buffer
materialisation at construction time.

DecimalBytePartsEncodingDecoder now returns LazyDecimalBytePartsArray
directly. GenericArray.getDecimal is reduced to the single-buffer case
only — the child-array branch is gone and the bounds / shape checks
shrink accordingly.

ScanIterator's truncate dispatch gains a LazyDecimalBytePartsArray case
that recursively truncates the child and rebuilds the record at the
clamped row count.

VortexInspectorTui's data-cell renderer recognises both decimal Array
flavours via a small tryDecimal helper that takes the getter as a
LongFunction; the per-row formatting path stays identical.

The two GenericArrayTest cases that exercised the child-array shape
(getDecimal_childArrayShape_decodesViaMostSignificantPart and
getDecimal_nullCellInMaskedChild_throws) move to the new
LazyDecimalBytePartsArrayTest, joined by a widening case (i32 child
under a decimal(15,2) parent) and the bounds / non-decimal-dtype
guards. The writer's DecimalBytePartsEncodingEncoderTest round-trip
now asserts the reassembled BigDecimal value rather than reaching into
GenericArray.child(0).

./mvnw verify green (13 modules SUCCESS, integration suite 40s).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@dfa1 dfa1 merged commit 22887cb into main Jun 16, 2026
6 checks passed
@dfa1 dfa1 deleted the feat/decbyteparts-lazy branch June 16, 2026 11:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant